home *** CD-ROM | disk | FTP | other *** search
- /*==========================================================================
- *
- * !BEST001.C Tuesday, April 12, 1994
- *
- * con_ str_ fil_ counter counter_reg dos_shell
- * supplementary source file 1 for The BESTLibrary
- *
- * Authored independently by George Vanous
- *
- *==========================================================================*/
-
-
- /* ------------------------------------------------------------------------ */
- /* ---------------------------- INCLUDE FILES --------------------------- */
-
- #include <dir.h>
- #include <alloc.h>
- #include <errno.h>
- #include <stdlib.h>
- #include <process.h>
- #include "!bestlib.h"
-
- /* ------------------------------------------------------------------------ */
- /* ------------------------------ MESSAGES ------------------------------ */
-
- #define MSG01 "\nThis is your first time using %s\nI, %s, hope you enjoy this program\n\n"
- #define MSG02 "\n%s has been used %d time"
- #define MSG03 "\nThere is %ld bytes of free RAM now available to %s\n"
- #define MSG04 "\nThis copy of %s is registered to %s\n"
- #define MSG05 "\nThis is the master copy of %s\nIt is registered to its author, %s\n"
- #define ERR01 "\n!!! ERROR !!! I cannot find the data file %s\n"
-
- /* ------------------------------------------------------------------------ */
-
-
- /*----------------------------------------------------------------------------
- * Shell to DOS.
- *
- * RETURNS:
- * = pointer to an error message
- * = NULL if no error message
- */
- char *dos_shell(void)
- {
- int error;
- char *commandpath, *textstring;
- struct ffblk ffblk;
-
- if ((commandpath = getenv("COMSPEC")) == NULL &&
- (commandpath = searchpath("COMMAND.COM")) == NULL) {
- if ((error = findfirst(commandpath = "COMMAND.COM", &ffblk, 0)) == NULL &&
- (error = findfirst(commandpath = "C:\COMMAND.COM", &ffblk, 0)) == NULL &&
- (error = findfirst(commandpath = "C:\DOS\COMMAND.COM", &ffblk, 0)) == NULL &&
- (error = findfirst(commandpath = "C:\BIN\COMMAND.COM", &ffblk, 0)) == NULL) {
- textstring = "Cannot find file COMMAND.COM -- initialize COMSPEC=[path]COMMAND.COM";
- return( textstring );
- }
- }
- video_set(TEXT);
- error = spawnl(P_WAIT, commandpath, commandpath, NULL);
-
- if (error == -1) {
- switch(errno) {
- case EINVAL : textstring = "Bad argument passed to COMMAND.COM"; break;
- case E2BIG : textstring = "Too many arguments passed to COMMAND.COM"; break;
- case ENOEXEC: textstring = "Internal error -- exitting strongly suggested"; break;
- case ENOMEM : textstring = "Out of memory -- cannot shell to DOS"; break;
- case ENOENT : textstring = "Cannot find file COMMAND.COM -- initialize COMSPEC=[path]COMMAND.COM";
- }
- }
- else if (!error) textstring = NULL;
- return( textstring );
- }
-
- /*----------------------------------------------------------------------------
- * Read, print, and increment the number of program executions.
- * Print a comment, depending on the current execution number.
- * Print the amount of available memory.
- *
- * "filename" - name of the text data file to read the number of program
- * executions from (this number must be the first byte)
- * - writes the incremented number of executions back to the file
- * "title" - name of the program
- * "author" - name of the author of the program
- * "msgs" - one comment will be randomly chosen from this array of
- * messages
- * "msg_num" - number of messages present
- *
- * RETURNS:
- * = file handle of the opened data file
- */
- FILE *fil_count(char *filename, char *title, char *author, char *msgs[], word msg_num)
- {
- word counter; // usage counter
- FILE *f; // file handle
-
- DASHES; // print one line of dashes
- if ((f = fopen(filename, "r+b")) == NULL) {
- fprintf(stderr, ERR01, filename); // file could not be opened
- exit(1); // abort with ERRORLEVEL 1
- }
-
- /* the first byte of the file is the usage counter -- get it */
- fread(&counter, sizeof(counter), 1, f);
-
- /* increment the counter and print the correct message */
- if (counter++ == 0)
- printf(MSG01, title, author); // print "first time used" message
- else {
- printf(MSG02, title, counter); // print number of program uses
- if (counter != 1) // if uses do not equal 1 then
- printf("s"); // pluralise
- }
- DOUBLESPACE;
-
- /* write the incremented counter back to the file */
- rewind(f); // go to beginning of file
- fwrite(&counter, sizeof(counter), 1, f);
-
- // the "fseek" is REQUIRED for the next "fread" to work???
- fseek(f, 0L, SEEK_CUR);
-
- printf(msgs[random(msg_num)], title);
- printf(MSG03, coreleft(), title); // print amount of available memory
- return( f ); // return file handle
- }
-
- /*----------------------------------------------------------------------------
- * Read, print, and increment the number of program executions.
- * Print to whom this program is registered.
- * Print the amount of available memory.
- *
- * "filename" - name of the text data file to read the number of program
- * executions from (this number must be the first byte)
- * - writes the incremented number of executions back to the file
- * "title" - name of the program
- * "author" - name of the author of the program
- * "registree" - name of the person to whom this program is registered
- *
- * RETURNS:
- * = file handle of the opened data file
- */
- FILE *fil_count_reg(char *filename, char *title, char *author, char *registree)
- {
- word counter; // usage counter
- FILE *f; // file handle
-
- DASHES; // print one line of dashes
- if ((f = fopen(filename, "r+b")) == NULL) {
- fprintf(stderr, ERR01, filename); // file could not be opened
- exit(1); // abort with ERRORLEVEL 1
- }
-
- /* the first byte of the file is the usage counter -- get it */
- fread(&counter, sizeof(counter), 1, f);
-
- /* increment the counter and print the correct message */
- if (counter++ == 0)
- printf(MSG01, title, author); // print "first time used" message
- else {
- printf(MSG02, title, counter); // print number of program uses
- if (counter != 1) // if uses do not equal 1 then
- printf("s"); // pluralise
- }
- DOUBLESPACE;
-
- /* write the incremented counter back to the file */
- rewind(f); // go to beginning of file
- fwrite(&counter, sizeof(counter), 1, f);
-
- // the "fseek" is REQUIRED for the next "fread" to work???
- fseek(f, 0L, SEEK_CUR);
-
- if (!str_cmp(author, registree)) // if this is registered to author then
- printf(MSG05, title, author); // print master copy message
- else // else
- printf(MSG04, title, registree); // print to whom this is registered
-
- printf(MSG03, coreleft(), title); // print amount of available memory
- return( f ); // return file handle
- }
-
- /*----------------------------------------------------------------------------
- * Return the length of a file, in bytes.
- *
- * "f" - file handle of file to return length of
- *
- * RETURNS:
- * = length of file in bytes
- */
- long fil_len(FILE *f)
- {
- long curpos, length;
-
- curpos = ftell(f); // save current position
- fseek(f, 0L, SEEK_END); // go to EOF
- length = ftell(f); // get EOF position relative to start
- fseek(f, curpos, SEEK_SET); // go back to original position
- return( length ); // return length of file, in bytes
- }
-
- /*----------------------------------------------------------------------------
- * Read the next string from the current file position.
- *
- * "size" - initial size of text input buffer
- * "f" - file handle of file to read from
- *
- * RETURNS:
- * = pointer to next string (file pointer is set to byte just beyond word)
- * = NULL if no string was found (file pointer is set to EOF)
- */
- char *fil_next_str(word *size, FILE *f)
- {
- char ch, // temporary character-holder
- *text; // text input buffer
- word index = 0, // index into text input buffer
- size_org; // original initial size of buffer
-
- text = (char *) malloc(size_org = *size);
-
- /* ignore initial whitespaces */
- for (ch = getc(f); !is_letternum(ch) && ch != QUOTE; ch = getc(f)) {
- if (ch == EOF) { // if we hit end of file
- free(text); // no match was found (free up memory)
- return( NULL ); // return NULL
- }
- }
-
- /* read in next string */
- if (ch == QUOTE) {
- do {
- if (ch == EOF) { // if we hit end of file
- free(text); // no match was found (free up memory)
- return( NULL ); // return NULL
- }
- while (index+2 >= *size) // allocate more memory if required
- text = (char *) realloc(text, *size += size_org);
- text[index++] = ch; // store next valid character
- ch = getc(f); // get next character
- } while (ch != QUOTE // loop until next character is a '"'
- && ch != CR && ch != LF); // or until it is a CR or LF
-
- if (ch == QUOTE) // if the last character was a '"'
- text[index++] = ch; // store it
- }
- else {
- for ( ; is_letternum(ch); ch = getc(f) ) {
- if (index+1 >= *size) // allocate more memory if required
- text = (char *) realloc(text, *size += size_org);
- text[index++] = ch; // store next valid character
- }
- }
-
- text[index] = NULL; // end string with NULL-terminator
- return( text ); // return next string
- }
-
- /*----------------------------------------------------------------------------
- * Read the next word from the current file position.
- *
- * "size" - initial size of text input buffer
- * "f" - file handle of file to read from
- *
- * RETURNS:
- * = pointer to next word (file pointer is set to byte just beyond word)
- * = NULL if no word was found (file pointer is set to EOF)
- */
- char *fil_next_word(word *size, FILE *f)
- {
- char ch, // temporary character-holder
- *text; // text input buffer
- word index = 0, // index into text input buffer
- size_org; // original initial size of buffer
-
- text = (char *) malloc(size_org = *size);
-
- /* ignore initial whitespaces */
- for (ch = getc(f); !is_letter(ch); ch = getc(f) ) {
- if (ch == EOF) { // if we hit end of file
- free(text); // no match was found (free up memory)
- return( NULL ); // return NULL
- }
- }
-
- /* read in next word */
- for ( ; is_letter(ch); ch = getc(f)) {
- if (index+1 >= *size) // allocate more memory if required
- text = (char *) realloc(text, *size += size_org);
- text[index++] = ch; // store valid alphabet character
- }
-
- text[index] = NULL; // end string with NULL-terminator
- return( text ); // return next word
- }
-
- /*----------------------------------------------------------------------------
- * Read from the current file position upto the first occurrence of a string.
- *
- * "str" - string to read up to
- * "size" - initial size of text input buffer
- * "f" - file handle of file to read from
- *
- * RETURNS:
- * = pointer to contents of file read in (file pointer is set to byte just
- * beyond match
- * = NULL if no match was found (file pointer is set to EOF)
- */
- char *fil_read_to(char *str, word *size, FILE *f)
- {
- char ch, // temporary character holder
- *text; // text input buffer
- int index_str; // index into string-to-read-to
- // must be integer because: fseek(f, -index_str, SEEK_CUR); (-ve seek)
- word index = 0, // index into text input buffer
- size_org; // original initial size of buffer
-
- text = (char *) malloc(size_org = *size);
- while (TRUE)
- {
- while ( (text[index++] = getc(f)) != str[0] ) {
- if (text[index-1] == EOF) { // if we hit end of file
- free(text); // no match was found (free up memory)
- return( NULL ); // return NULL
- }
- if (index+1 >= *size) // allocate more memory if required
- text = (char *) realloc(text, *size += size_org);
- }
-
- if (str_len(str) == 1) {
- text[1] = NULL; // end string with NULL-terminator
- return( text ); // return pointer to text input holder
- }
- else {
- for (index_str = 0; (ch = getc(f)) == str[++index_str]; );
- if (index_str == str_len(str)) { // if we found the string
- fseek(f, -1, SEEK_CUR); // rewind to byte just after match
- if (index+index_str > *size) // allocate more memory if required
- text = (char *) realloc(text, *size = index_str+index);
- str_copy(text + index, str+1);
- return( text ); // return pointer to text input holder
- }
- else if (ch == EOF) { // if we hit end of file
- free(text); // no match was found (free up memory)
- return( NULL ); // return NULL
- }
- }
-
- fseek(f, -index_str, SEEK_CUR); // false alarm -- rewind
- }
- }
-
- /*----------------------------------------------------------------------------
- * Read from the current file position upto the first occurrence of a string.
- * All comments (beginning with a ';'), blank lines, and extra spaces are
- * stripped to conserve memory.
- *
- * "str" - string to read up to
- * "size" - initial size of text input buffer
- * "f" - file handle of file to read from
- *
- * RETURNS:
- * = pointer to contents of file read in (file pointer is set to byte just
- * beyond match
- * = NULL if no match was found (file pointer is set to EOF)
- */
- char *fil_read_to_strip(char *str, word *size, FILE *f)
- {
- char ch, // temporary character holder
- *text; // text input buffer
- int index_str, // index into string-to-read-to
- quotes = FALSE; // [inside a quote?] flag
- word index = 0, // generic buffer character index
- size_org, // original initial size of buffer
- spaces = 1; // count of ' ' (space) characters
-
- text = (char *) malloc(size_org = *size);
- while (TRUE)
- {
- do {
- ch = getc(f); // get next character
- while (TRUE)
- {
- if (ch != ' ') spaces = 0; // reset space counter
-
- if (ch == '[') {
- if (!quotes) quotes = 2;
- break;
- }
- if (ch == ']') {
- if (quotes == 2) quotes = FALSE;
- break;
- }
- if (ch == '"') {
- if (!quotes) quotes = 1;
- else if (quotes == 1) quotes = FALSE;
- break;
- }
-
- if (ch == CR) {
- // clear out all following CR/LF pairs
- for (ch = getc(f), ch = getc(f); ch == CR || ch == LF; ch = getc(f));
- quotes = FALSE, spaces = 1;
- if (index) { // if not first character
- text[index++] = LF; // store one EOL character
- if (index+1 >= *size) // allocate more memory if required
- text = (char *) realloc(text, *size += size_org);
- }
- continue; // check out new character
- }
-
- if (!quotes) {
- if (ch == ';') { // remove all comments
- if (text[index-1] == ' ')
- index--;
- while ((ch = getc(f)) != CR && ch != EOF);
- continue; // check out new character
- }
- if (ch == '=') { // ignore empty spaces surrounding '='
- if (text[index-1] == ' ')
- index--;
- spaces = 1; // if it is a space, will remove it
- break; // go store '='
- }
- if (ch == ' ' && ++spaces > 1) { // ignore 2+ blank spaces
- while ((ch = getc(f)) == ' ');
- continue; // check out new character
- }
- }
-
- if (ch == EOF) { // if we hit end of file
- free(text); // no match was found (free up memory)
- return( NULL ); // return NULL
- }
- break; // character is valid, so go store it
- }
- text[index++] = ch; // store valid character
- if (index+1 >= *size) // allocate more memory if required
- text = (char *) realloc(text, *size += size_org);
- } while (ch != str[0]);
-
- if (str_len(str) == 1) {
- text[1] = NULL; // end string with NULL-terminator
- return( text ); // return pointer to text input holder
- }
- else {
- for (index_str = 0; (ch = getc(f)) == str[++index_str]; );
- if (index_str == str_len(str)) { // if we found the string
- fseek(f, -1, SEEK_CUR); // rewind to byte just after match
- if (index+index_str > *size) // allocate more memory if required
- text = (char *) realloc(text, *size = index_str+index);
- str_copy(text + index, str+1);
- return( text ); // return pointer to text input holder
- }
- else if (ch == EOF) { // if we hit end of file
- free(text); // no match was found (free up memory)
- return( NULL ); // return NULL
- }
- }
-
- fseek(f, -index_str, SEEK_CUR); // false alarm -- rewind
- }
- }
-
- /*----------------------------------------------------------------------------
- * Search a file for a string and set the file pointer just past it.
- *
- * "str" - string to skip past
- * "f" - file handle of file to read from
- *
- * RETURNS:
- * The file pointer is set to one byte beyond the match or
- * to the end-of-file if no match was found.
- * = number of bytes scanned upto (and including) last byte of match
- * = FALSE if no match was found
- */
- word fil_skip_past(char *str, FILE *f)
- {
- int index; // input string character index
- char ch; // temporary character holder
- word offset = 0; // file character offset
-
- while (TRUE)
- {
- for (offset++; (ch = getc(f)) != str[0]; offset++)
- if (ch == EOF) return( FALSE );
-
- if (str_len(str) == 1)
- return( offset );
- else {
- for (index = 0, offset++; (ch = getc(f)) == str[++index]; offset++);
- if (index == str_len(str)) { // if we found the string
- fseek(f, -1, SEEK_CUR); // rewind to byte just after match
- return( offset-1 ); // return ending offset of find
- }
- else if (ch == EOF) // if we hit end of file
- return( FALSE ); // return FALSE
- }
-
- fseek(f, -index, SEEK_CUR); // false alarm -- rewind
- offset -= index; // false alarm -- rewind
- }
- }
-
- /*----------------------------------------------------------------------------
- * Search a file for a string and set the file pointer to it.
- *
- * "str" - string to set file pointer to
- * "f" - file handle of file to read from
- *
- * RETURNS:
- * The file pointer is set to the first byte of the first match
- * the end-of-file if no match was found.
- * = number of bytes scanned upto (and including) first byte of match
- * file pointer set to the first byte of match
- * = FALSE if no match was found
- * file pointer set to end-of-file
- */
- word fil_skip_to(char *str, FILE *f)
- {
- int index; // input string character index
- char ch; // temporary character holder
- word offset = 0; // file character offset
-
- while (TRUE)
- {
- for (offset++; (ch = getc(f)) != str[0]; offset++)
- if (ch == EOF) return( FALSE );
-
- if (str_len(str) == 1) {
- fseek(f, -1, SEEK_CUR); // rewind to beginning of match
- return( offset );
- }
- else {
- for (index = 0, offset++; (ch = getc(f)) == str[++index]; offset++);
- if (index == str_len(str)) { // if we found the string
- fseek(f, -(index+1), SEEK_CUR); // rewind to first byte of match
- return( offset-index ); // return beginning offset of find
- }
- else if (ch == EOF) // if we hit end of file
- return( FALSE ); // return FALSE
- }
-
- fseek(f, -index, SEEK_CUR); // false alarm -- rewind
- offset -= index; // false alarm -- rewind
- }
- }
-
- /*----------------------------------------------------------------------------
- * Return the next string from a string in memory.
- *
- * "text" - string to get the next string from
- *
- * RETURNS:
- * = pointer to next string
- */
- char *str_next_str(char *text)
- {
- char *str; // string to return
- word begin, // offset to beginning of next word
- index; // index into string to read from
-
- /* ignore initial whitespaces */
- for (index = 0; !is_letternum(text[index]) && text[index] != QUOTE; index++)
- if (!text[index]) return( NULL ); // if we hit end of string, return NULL
-
- /* get length of next word */
- begin = index; // save offset to beginning of nextword
- if (text[index] == QUOTE) {
- while (TRUE) {
- if (!text[index]) // if we hit end of string
- return( NULL ); // return NULL
- if (text[++index] == QUOTE) { // if next character is a '"'
- index++; // make sure the end quote is stored
- break; // break out of loop
- }
- if (text[index] == CR ||
- text[index] == LF) // if we hit end of line
- break; // break out of loop
- }
- }
- else
- while (is_letternum(text[++index]));
-
- /* allocate memory and make copy of the word */
- str = (char *) malloc(index-begin + 1);
- mem_copy(str, text+begin, index-begin);
- str[index-begin] = NULL; // end string with NULL-terminator
-
- return( str ); // return next string
- }
-
- /*----------------------------------------------------------------------------
- * Return the next word from a string in memory.
- *
- * "text" - string to get the next word from
- *
- * RETURNS:
- * = pointer to next word
- */
- char *str_next_word(char *text)
- {
- char *str; // str input buffer
- word begin, // offset to beginning of next word
- index; // index into string to read from
-
- /* ignore initial whitespaces */
- for (index = 0; !is_letter(text[index]); index++);
-
- /* get length of next word */
- for (begin = index; is_letter(text[++index]); );
-
- /* allocate memory and make a copy of the word */
- str = (char *) malloc(index-begin + 1);
- mem_copy(str, text+begin, index-begin);
- str[index-begin] = NULL; // end word with NULL-terminator
-
- return( str ); // return next word
- }
-
- /*----------------------------------------------------------------------------
- * Convert the boolean FALSE or TRUE into the string "FALSE" or "TRUE",
- * respectively.
- *
- * "bool" - boolean to convert
- *
- * RETURNS:
- * = "TRUE" if "bool" = TRUE
- * = "FALSE" if "bool" = FALSE
- */
- char *con_bool_to_str(boolean bool)
- {
- if (!bool) // is boolean = FALSE
- return( "FALSE" ); // yes, so return "FALSE"
- return( "TRUE" ); // else return "TRUE"
- }
-
- /*----------------------------------------------------------------------------
- * Convert the numeric representation of a color to its string equivalent.
- *
- * "color" - color to convert
- *
- * RETURNS:
- * = string representation of "color"
- * = NULL if "color" is not a valid color
- */
- char *con_color_to_str(byte color)
- {
- if (color == BLACK ) return( "BLACK" );
- if (color == BLUE ) return( "BLUE" );
- if (color == GREEN ) return( "GREEN" );
- if (color == CYAN ) return( "CYAN" );
- if (color == RED ) return( "RED" );
- if (color == MAGENTA ) return( "MAGENTA" );
- if (color == BROWN ) return( "BROWN" );
- if (color == LIGHTGREY ) return( "LIGHTGREY" );
- if (color == DARKGREY ) return( "DARKGREY" );
- if (color == LIGHTBLUE ) return( "LIGHTBLUE" );
- if (color == LIGHTGREEN ) return( "LIGHTGREEN" );
- if (color == LIGHTCYAN ) return( "LIGHTCYAN" );
- if (color == LIGHTRED ) return( "LIGHTRED" );
- if (color == LIGHTMAGENTA) return( "LIGHTMAGENTA" );
- if (color == YELLOW ) return( "YELLOW" );
- if (color == WHITE ) return( "WHITE" );
- return( NULL ); // no color matched -- return NULL
- }
-
- /*----------------------------------------------------------------------------
- * Convert the string representation of a boolean value into boolean FALSE or TRUE,
- * respectively.
- *
- * "str" - word to convert
- *
- * RETURNS:
- * = TRUE if "str" = "TRUE"
- * = FALSE if "str" = "FALSE"
- * = -1 if "str" is not a valid boolean word
- */
- shortint con_str_to_bool(char *str)
- {
- str_case_up(str); // make sure we are in uppercase
- if (!str_cmp(str, "FALSE")) // is string = "FALSE"
- return( FALSE ); // yes, so return FALSE
- if (str_cmp(str, "TRUE")) // is string = "TRUE"
- return( -1 ); // no, so return -1
- return( TRUE ); // else return TRUE
- }
-
- /*----------------------------------------------------------------------------
- * Convert the name of a color into its numeric equivalent.
- *
- * "str" - color to convert
- *
- * RETURNS:
- * = color value
- * = -1 if "str" is not a valid color
- */
- shortint con_str_to_color(char *str)
- {
- str_case_up(str); // make sure we are in uppercase
- if (!str_cmp(str, "BLACK") ) return( BLACK );
- if (!str_cmp(str, "BLUE") ) return( BLUE );
- if (!str_cmp(str, "GREEN") ) return( GREEN );
- if (!str_cmp(str, "CYAN") ) return( CYAN );
- if (!str_cmp(str, "RED") ) return( RED );
- if (!str_cmp(str, "MAGENTA") ) return( MAGENTA );
- if (!str_cmp(str, "BROWN") ) return( BROWN );
- if (!str_cmp(str, "LIGHTGREY") ) return( LIGHTGREY );
- if (!str_cmp(str, "DARKGREY") ) return( DARKGREY );
- if (!str_cmp(str, "LIGHTBLUE") ) return( LIGHTBLUE );
- if (!str_cmp(str, "LIGHTGREEN") ) return( LIGHTGREEN );
- if (!str_cmp(str, "LIGHTCYAN") ) return( LIGHTCYAN );
- if (!str_cmp(str, "LIGHTRED") ) return( LIGHTRED );
- if (!str_cmp(str, "LIGHTMAGENTA")) return( LIGHTMAGENTA );
- if (!str_cmp(str, "YELLOW") ) return( YELLOW );
- if (!str_cmp(str, "WHITE") ) return( WHITE );
- return( -1 ); // no color matched -- return -1
- }
-
- /*============================== END-OF-FILE =============================*/
-